// Include guards
#ifndef CVSUBSYSTEMMANAGER_H
#define CVSUBSYSTEMMANAGER_H

#include <vector>
#include <stdlib.h>
#include "ISubSystem.h"
#include "Logger/ILogger.h"
#include "Logger/NullLogger.h"

#include "Exceptions/Exception.h"

/**
 * Singleton management class for subsystems
 */
class SubSystemManager
{
	public:

	// Life-cycle
	virtual ~SubSystemManager();

	// methods

	/**
	 * Returns the singleton-SubSystemManager
	 */
	static SubSystemManager* getInstance();

	/**
	 * Registers a new subsystem into the manager. The ownership of the object is transferred to
	 * the manager.
	 * @param subSystem	ISubSystem to register
	 * @throws Exception, if another subsystem with the same name is already registered
	 */
	void registerSubSystem(ISubSystem& subSystem);

	/**
	 * Unregisters an existing subsystem from the manager
	 * @param subSystemName	Name of the subsystem to unregister
	 * @param shutDownFirst Set to false to prevent the manager from shutting down the subsystem
	 *			prior to unregistering. Defaults to true.
	 * @throws Exception, if subsystem does not exist
	 */
	void unregisterSubSystem(const char* subSystemName, bool shutDownFirst = true);

	/**
	 * Searches for subsystem by name from the manager.
	 * @param subSystemName	Name of the subsystem to search for
	 * @return ISubSystem-implementing object or null if not found
	 */
	ISubSystem* getSubSystemByName(const char* subSystemName);

	/**
	 * Attempts to start all the registered subsystems
	 * @throws Exception, if start up fails
	 */
	void startEnvironment();

	/**
	 * Gets the current logger used by manager & subsystems
	 * @return Object implementing ILogger-interface
	 */
	ILogger* getLogger() { return m_logger; }

	/**
	 * Sets the logger for the manager and subsystems, if an existing logger was found, it will be deleted
	 * The new logger is given to all current subsystems
	 * @param logger	Object implementing ILogger-interface, ownership is transferred to SubSystemManager
	 */
	void setLogger(ILogger* logger);

	/**
	 * Destroys the singleton to get proper shutdown and then calls exit( exitValue );
	 * @param exitValue		Exit value to return to the OS, usually 0 for normal shutdown, other values act as error codes
	 */
	void terminate(int exitValue);

private:
	// Internal methods and data

	/**
	 * Hidden ctor
	 */
	SubSystemManager();

	/**
	 * Called by destructor, shuts down everything
	 */
	void shutdownEnvironment();

	bool m_subSystemsStarted;

	ILogger* m_logger;

	/**
	 * Map to hold subsystems
	 */
	typedef std::vector<ISubSystem* >::iterator SubSystem_vec_iter;
	std::vector<ISubSystem* > m_subSystems;

};

#endif // #ifndef CVSUBSYSTEMMANAGER_H
